﻿using System.IO;
using System;

namespace LogNaga.Logs
{
	/// <summary>
	/// 以文本流的方式记录Log
	/// </summary>
	public class TextWriterLog : TextLog, IDisposable
	{
		// 是否拥有当前文件的lock
		private readonly bool ifLockingCurrentTextWriter;
		private volatile bool disposed;
		private TextWriter textWriter;
		private ExceptionFormatter exceptionFormatter;

		/// <summary>
		/// 创建TextWriterLog实例
		/// </summary>
		/// <param name="writer"><see cref="System.IO.TextWriter"/></param>
		/// <remarks>
		/// 默认这个<paramref name="writer"/>是不拥有TextWriter的
		/// </remarks>
		public TextWriterLog(TextWriter writer)
			: this(writer, false)
		{
		}

		/// <summary>
		/// 创建TextWriterLog实例
		/// </summary>
		/// <param name="writer"><see cref="System.IO.TextWriter"/></param>
		/// <param name="ifLockingCurrentTextWriter">The responbility level this instance has over the <paramref name="writer"/></param>
		public TextWriterLog(TextWriter writer, bool ifLockingCurrentTextWriter)
			: this(writer, ifLockingCurrentTextWriter, ExceptionFormatterHelper.Default)
		{
		}

		/// <summary>
		/// 创建TextWriterLog实例
		/// </summary>
		/// <param name="writer"><see cref="System.IO.TextWriter"/></param>
		/// <param name="ifLockingCurrentTextWriter">The responbility level this instance has over the <paramref name="writer"/></param>
		/// <param name="exceptionFormatter">设置<see cref="ExceptionFormatter"/></param>
		public TextWriterLog(TextWriter writer, bool ifLockingCurrentTextWriter, ExceptionFormatter exceptionFormatter)
		{
			if (writer == null)
			{
				throw new ArgumentNullException("writer");
			}

			this.ifLockingCurrentTextWriter = ifLockingCurrentTextWriter;
			this.disposed = false;
			this.textWriter = writer;
			this.exceptionFormatter = exceptionFormatter;
		}

		#region Log.Write

		public sealed override void WriteToDestination(Error errorEntry)
		{
			//首先需要判断dispose的问题
			if (this.disposed)
			{
				throw new ObjectDisposedException(GetType().FullName);
			}

			try
			{
				// TextWriter负责记录的是ErrorEntry的ErrorMessage字段
				this.textWriter.WriteLine(errorEntry.ErrorMessage);
				this.textWriter.WriteLine();
				this.textWriter.Flush();
			}
			catch (Exception ex)
			{
				//如果是严重级别的异常就扔出去
				if (ex.IsImportant()) { throw; }
			}
		}

		public override ExceptionFormatter GetExceptionFormatter()
		{
			return this.exceptionFormatter;
		}

		#endregion

		#region Dispose

		/// <summary>
		/// Dispose
		/// </summary>
		public void Dispose()
		{
			this.Dispose(true);
			GC.SuppressFinalize(this);
		}

		/// <summary>
		/// Dispose的实现
		/// </summary>
		/// <param name="disposing">是否正在执行Dispose方法</param>
		protected virtual void Dispose(bool disposing)
		{
			if (this.disposed) return;

			try
			{
				if (disposing)
				{
					if (this.textWriter != null)
					{
						//如果正锁着这个TextWriter就释放掉
						if (ifLockingCurrentTextWriter)
						{
							this.textWriter.Dispose();
						}
						//接触引用
						this.textWriter = null;
					}
				}
			}
			finally
			{
				this.disposed = true;
			}
		}

		#endregion
	}
}
